/*
 * Android Runner is a multiplayer GPS game fully written by Xurxo Mendez Perez
 * 
 * Copyright (C) 2009 Xurxo Mendez Perez
 *   
 * This file is part of Android Runner.
 * 
 * Android Runner is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * Android Runner is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with Android Runner.  If not, see <http://www.gnu.org/licenses/>.
 */

package es.sonxurxo.gpsgame.client.cv.activity;

import java.util.ArrayList;
import java.util.List;

import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.DialogInterface.OnClickListener;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnLongClickListener;
import android.view.ViewGroup.LayoutParams;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.ScrollView;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.AdapterView.OnItemClickListener;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.ItemizedOverlay;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.OverlayItem;

import es.sonxurxo.gpsgame.client.R;
import es.sonxurxo.gpsgame.client.cv.common.actions.CommonActions;
import es.sonxurxo.gpsgame.client.cv.common.dialogs.CommonDialogs;
import es.sonxurxo.gpsgame.client.cv.to.Options;
import es.sonxurxo.gpsgame.client.cv.util.ImageResolver;
import es.sonxurxo.gpsgame.client.cv.util.constants.CustomResultCodes;
import es.sonxurxo.gpsgame.client.cv.util.location.LocationToGeoPointConversor;
import es.sonxurxo.gpsgame.client.model.service.game.HttpGameServiceImpl;
import es.sonxurxo.gpsgame.client.model.service.player.HttpPlayerServiceImpl;
import es.sonxurxo.gpsgame.client.model.service.to.Game;
import es.sonxurxo.gpsgame.client.model.service.to.Item;
import es.sonxurxo.gpsgame.client.model.service.to.Message;
import es.sonxurxo.gpsgame.client.model.service.to.Player;
import es.sonxurxo.gpsgame.client.model.service.to.PublicPlayerProfileTO;
import es.sonxurxo.gpsgame.client.model.service.to.Question;
import es.sonxurxo.gpsgame.client.model.service.to.response.AnswerQuestionResponseTO;
import es.sonxurxo.gpsgame.client.model.service.to.response.GenericGameResponseTO;
import es.sonxurxo.gpsgame.client.model.service.to.response.GetItemResponseTO;
import es.sonxurxo.gpsgame.client.model.service.to.response.InGamePlayerInfoTO;
import es.sonxurxo.gpsgame.client.model.service.to.response.StartOrContinueGameResponseTO;
import es.sonxurxo.gpsgame.client.util.exception.ServerException;

/**
 * 
 * @author "Xurxo Mendez Perez"
 *
 */
public class MapViewActivity extends MapActivity implements LocationListener,
Abandonable{

	public static final int SEND_MESSAGE_REQUEST_CODE = 0;
	public static final int OPTIONS_REQUEST_CODE = 1;
	
	private static final int ABANDON_ID = Menu.FIRST;
	private static final int SEND_BROADCAST_ID = Menu.FIRST + 1;
	private static final int OPTIONS_ID = Menu.FIRST + 2;
	private static final int RANKING_ID = Menu.FIRST + 3;

	private static final int RANKING_DIALOG_ID = CommonDialogs.FIRST_CUSTOM_DIALOG_ID;
    private static final int PLAYER_TAPPED_DIALOG_ID = RANKING_DIALOG_ID + 1;
    private static final int ABANDON_DIALOG_ID = RANKING_DIALOG_ID + 2;
    private static final int SHOW_QUESTION_DIALOG_ID = RANKING_DIALOG_ID + 3;

    private Player player;
	private Game game;
	private StartOrContinueGameResponseTO sOCGRTO;
	private GenericGameResponseTO genericGameResponseTO;
	private GetItemResponseTO getItemResponseTO;
	private AnswerQuestionResponseTO answerQuestionResponseTO;
	private PublicPlayerProfileTO publicPlayerProfileTO;
	
	private LocationManager lm;
	private MapController mc;
	private MapView mv;
	
	private ItemsOverlay itemsLayer;
	private PlayersOverlay playersLayer;
	private MyPlayerOverlay meLayer;
	
	private LinearLayout zoomView;
	
	private int lastNumberOfPlayers;
	
	private ScrollView rankingScrollView;
	private TableLayout rankingTable;
	private TableLayout playerTappedTable;
	private TableLayout questionTable;
	
	private String tappedPlayerLogin;
	private long questionId;
	
	private Options options = new Options(true, true, true, true, true, true, 0);
	
	private StartGameTask startGameTask = new StartGameTask();
	private ViewPublicPlayerProfileTask vPPPTask = new ViewPublicPlayerProfileTask();
	private AnswerQuestionTask answerQuestionTask = new AnswerQuestionTask();
	
	private GetItemTask getItemTask = new GetItemTask();
	private UpdateLocationTask updateLocationTask = new UpdateLocationTask();
	
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.map_view_page);
		Bundle extras = getIntent().getExtras();
		player = (Player)extras.getSerializable("player");
		game = (Game)extras.getSerializable("game");
		
		lm = (LocationManager)
		this.getSystemService(Context.LOCATION_SERVICE);
		
//		launchStartGameThread();
	}

	@Override
	protected boolean isRouteDisplayed() {

		return true;
	}
	
	@Override
	protected void onPause() {
		lm.removeUpdates(this);
		super.onPause();
	}

	@Override
	protected void onResume() {
		try {
			dismissDialog(CommonDialogs.CONNECTING_TO_SERVER_DIALOG_ID);
		} catch (Exception e) {
			
		}
		launchStartGameThread();
		super.onResume();
		try {
			dismissDialog(CommonDialogs.CONNECTING_TO_SERVER_DIALOG_ID);
		} catch (Exception e) {
			
		}
	}

	private void doStartGame() {
		player.setPoints(sOCGRTO.getPoints());
		player.setNumberOfItems(sOCGRTO.getNumberOfItems());
		genericGameResponseTO = sOCGRTO.getGenericGameResponseTO();
		lastNumberOfPlayers = genericGameResponseTO.getInGamePlayerInfoTOs().size();
		
		mv = (MapView)findViewById(R.id.map);

		lm = (LocationManager)
		this.getSystemService(Context.LOCATION_SERVICE);
		lm.requestLocationUpdates(LocationManager.GPS_PROVIDER,
				1000, 2, this);
//				options.getUpdatesInterval(), 10, this);
		
		// Add the items
		if (itemsLayer == null) {
			itemsLayer = new ItemsOverlay(
					getResources().getDrawable(R.drawable.coin));
			mv.getOverlays().add(itemsLayer);
		}

		// Add other players
		if (playersLayer == null) {
			playersLayer = new PlayersOverlay(
					getResources().getDrawable(
						ImageResolver.getOtherInGameImageId(R.drawable.face1)));
			mv.getOverlays().add(playersLayer);
		}

		player.setLocation(
				LocationToGeoPointConversor.getGeoPoint(lm.getLastKnownLocation(LocationManager.GPS_PROVIDER)));
		if (meLayer == null) {
			meLayer = new MyPlayerOverlay(
					getResources().getDrawable(
						ImageResolver.getMyInGameImageId(player.getImageId())));
			mv.getOverlays().add(meLayer);
		}

		mc = mv.getController();
		if (options.isFollowMe()) {
			mc.animateTo(player.getLocation());
			mc.setZoom(18);
		}
		
		mv.setSatellite(true);
		mv.displayZoomControls(true);
		
		if (zoomView == null) {
			zoomView = (LinearLayout) mv.getZoomControls();
	
			zoomView.setLayoutParams(
					new ViewGroup.LayoutParams (
							ViewGroup.LayoutParams.WRAP_CONTENT, 
							ViewGroup.LayoutParams.WRAP_CONTENT));
	
			
			mv.addView(zoomView);
		}
	}
	
	private void launchStartGameThread() {
		startGameTask.setLogin(player.getLogin());
		Thread startGameThread = new Thread(null, startGameTask, "StartGame");
		startGameThread.start();
		showDialog(CommonDialogs.CONNECTING_TO_SERVER_DIALOG_ID);
	}

	private void checkNumberOfPlayers() {
		int diff = genericGameResponseTO.getInGamePlayerInfoTOs().size() - 
		lastNumberOfPlayers;
		if (options.isNotifyJoins()) {
			if (diff == 1) {
				Toast.makeText(this, "One player has joined the game", Toast.LENGTH_LONG).show();
			}
				
			else if (diff > 1) {
				Toast.makeText(this, String.valueOf(diff) +  
						"players have joined the game", Toast.LENGTH_LONG).show();
			}
			lastNumberOfPlayers = lastNumberOfPlayers + diff;
		}
	}

	private void checkIncomingMessages() {
		List<Message> messageList = genericGameResponseTO.getMessages();
		for (Message m:messageList) {
			boolean notify = true;
			switch (m.getType()) {
			case Message.PLAYER_BROADCAST_MESSAGE:
				if (!options.isNotifyMessages())
					notify = false;
				break;
			case Message.PLAYER_PERSONAL_MESSAGE:
				if (!options.isNotifyMessages())
					notify = false;
				break;
			case Message.SYSTEM_PLAYER_ABANDONED_MESSAGE:
				if (!options.isNotifyLeaves())
					notify = false;
				break;
			case Message.SYSTEM_PLAYER_GETS_ITEM_MESSAGE:
				if (!options.isNotifyGets())
					notify = false;
				break;
			}
			if (notify) {
				String message = "Info : " + m.getMessageBody();
				if (m.getSenderLogin() != null)
					message = m.getSenderLogin() + " says : \n" + m.getMessageBody();
				
				Toast.makeText(this, message, Toast.LENGTH_LONG).show();
			}
		}
	}
	
	private void startFinishing() {
		launchGetPublicPlayerProfileThread();
	}
	
	private void launchGetPublicPlayerProfileThread() {
		vPPPTask.setLogin(player.getLogin());
		Thread vPPPThread = new Thread(null, vPPPTask, "Login");
		vPPPThread.start();
		showDialog(CommonDialogs.CONNECTING_TO_SERVER_DIALOG_ID);
	}

	private void doContinueFinishing() {
			player.setBestRank(publicPlayerProfileTO.getBestRank());
			player.setMaxPoints(publicPlayerProfileTO.getMaxPoints());
			player.setTotalPoints(publicPlayerProfileTO.getTotalPoints());
			
			CommonActions.launchAbandonGameThread(player, game, this);
	}

	private void update() {
		if (genericGameResponseTO.isHasFinished()) {
			lm.removeUpdates(this);
			startFinishing();
			return;
		}
		else {
			if (genericGameResponseTO.getVisibleItems().size() != 0) {
				itemsLayer.update();
			}
			if (genericGameResponseTO.getInGamePlayerInfoTOs().size() != 0) {
				playersLayer.update();
			}
			meLayer.update();
			checkNumberOfPlayers();
		}

		checkIncomingMessages();
		if (options.isFollowMe())
			mc.animateTo(player.getLocation());
		else {
			mc.animateTo(mv.getMapCenter());
		}
	}

	/* ******************************************************
	 * 
	 * Ranking
	 * 
	 *******************************************************/
	
	private List<InGamePlayerInfoTO> prepareRankingTable() {
    	List<InGamePlayerInfoTO> plTOList = 
    		genericGameResponseTO.getInGamePlayerInfoTOs();
    	boolean contains = false;
    	for (InGamePlayerInfoTO plTO:plTOList) 
    		if (plTO.getLogin().equals(player.getLogin()))
    			contains = true;
    	if (!contains)
    		plTOList.add(new InGamePlayerInfoTO(
    			player.getLogin(), player.getPoints(), player.getNumberOfItems(), 
    			player.getLocation(), player.getImageId()));
    	plTOList = orderList(plTOList);
    	return plTOList;
	}
	
	private void fillRankingHeader(TableLayout table) {
		
        TableRow tr = new TableRow(this);

        TextView tvLogin = new TextView(this);
    	tvLogin.setText("Player");
    	tvLogin.setGravity(Gravity.CENTER);
    	tvLogin.setTextColor(Color.CYAN);
    	tvLogin.setWidth(80);
    	
    	TextView tvPoints = new TextView(this);
    	tvPoints.setText("Pts");
    	tvPoints.setGravity(Gravity.CENTER);
    	tvPoints.setTextColor(Color.CYAN);
    	tvPoints.setWidth(60);
    	
    	TextView tvItems = new TextView(this);
    	tvItems.setGravity(Gravity.CENTER);
    	tvItems.setText("Items");
    	tvItems.setTextColor(Color.CYAN);
    	tvItems.setWidth(60);

    	tr.addView(new TextView(this));
    	tr.addView(new TextView(this));
    	tr.addView(tvLogin);
    	tr.addView(tvPoints);
    	tr.addView(tvItems);
    	tr.setPadding(0, 10, 0, 10);
    	table.addView(tr);		
	}
	
	private void fillRankingTable() {
		rankingTable = new TableLayout(this);

		fillRankingHeader(rankingTable);
		List<InGamePlayerInfoTO> plTOList = prepareRankingTable();		
		TableRow tr;
		
		ImageView image;
		TextView tvPosition, tvLogin, tvPoints, tvItems;
		int textColor;

    	for (int i=0;i<plTOList.size();i++) {
    		final String login = plTOList.get(i).getLogin();
        	tr = new TableRow(this);
        	image = new ImageView(this);
        	if (player.getLogin().equals(plTOList.get(i).getLogin())) {
        		image.setImageDrawable(
        				getResources().getDrawable(player.getImageId()));
        		textColor = Color.GREEN;
        	}
        	else {
        		image.setImageDrawable(
        				getResources().getDrawable(plTOList.get(i).getImageId()));
        		textColor = Color.WHITE;
        	}
        	LinearLayout l = new LinearLayout(this);
        	l.addView(image);
        	l.setGravity(Gravity.CENTER);
        	tvPosition = new TextView(this);
        	tvPosition.setGravity(Gravity.CENTER);
        	tvPosition.setText(String.valueOf(i+1));
        	tvPosition.setTextColor(textColor);
        	tvPosition.setWidth(10);
        	
        	tvLogin = new TextView(this);
        	tvLogin.setGravity(Gravity.CENTER);
        	tvLogin.setText(plTOList.get(i).getLogin());
        	tvLogin.setTextColor(textColor);
        	tvLogin.setWidth(80);
        	
        	tvPoints = new TextView(this);
        	tvPoints.setGravity(Gravity.CENTER);
        	tvPoints.setText(String.valueOf(plTOList.get(i).getPoints()));
        	tvPoints.setTextColor(textColor);
        	tvPoints.setWidth(60);
        	
        	tvItems = new TextView(this);
        	tvItems.setGravity(Gravity.CENTER);
        	tvItems.setText(String.valueOf(plTOList.get(i).getNumberOfItems()));
        	tvItems.setTextColor(textColor);
        	tvItems.setWidth(60);

        	tr.addView(tvPosition);
        	tr.addView(l);
        	tr.addView(tvLogin);
        	tr.addView(tvPoints);
        	tr.addView(tvItems);
        	
        	if (!plTOList.get(i).getLogin().equals(player.getLogin())) {
        		tr.setOnLongClickListener(new OnLongClickListener() {

					public boolean onLongClick(View arg0) {
						tappedPlayerLogin = login;
						showDialog(PLAYER_TAPPED_DIALOG_ID);
						return false;
					}
        			
        		});
        	}
        	rankingTable.addView(tr);
    	}
	}
	
	private void fillQuestion() {
		questionTable.removeAllViews();

		TableRow tr = new TableRow(this);
		
		TextView tvQuestion;
		tvQuestion = new TextView(this);
        tvQuestion.setText(getItemResponseTO.getQuestion().getQuestion());
        tr.addView(tvQuestion);
        questionTable.addView(tr);
        
		ListView optionsList = new ListView(this);
		String [] options = {getItemResponseTO.getQuestion().getOption1(),
				getItemResponseTO.getQuestion().getOption2(),
				getItemResponseTO.getQuestion().getOption3()};
		ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
		        android.R.layout.simple_spinner_dropdown_item,
		            options);
		optionsList.setAdapter(adapter);
		optionsList.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
		optionsList.setItemChecked(0, true);
		
		tr = new TableRow(this);
        tr.addView(optionsList);
        questionTable.addView(tr);
        
		optionsList.setOnItemClickListener(new AnswererClickListener(
				getItemResponseTO.getQuestion(), questionId));
	}

	private class AnswererClickListener implements OnItemClickListener {
		
		private Question question;
		private long questionId;
		
		public AnswererClickListener(Question question, long questionId) {
			this.question = question;
			this.questionId = questionId;
		}
		
		public void onItemClick(AdapterView<?> arg0, View arg1, int position,
				long arg3) {
			if (position == question.getAnswer())
				launchAnswerQuestionThread(questionId);
			else {
				String rightAnswer = new String();
				switch(question.getAnswer()) {
				case 0:
					rightAnswer = "\"" + question.getOption1();
					break;
				case 1:
					rightAnswer = "\"" + question.getOption2();
					break;
				case 2:
					rightAnswer = "\"" + question.getOption3();
					break;
				}
				rightAnswer = rightAnswer.concat("\"");
				Toast.makeText(MapViewActivity.this, "Sorry, the right answer was " +
						rightAnswer, Toast.LENGTH_LONG).show();
			}
			try {
				dismissDialog(SHOW_QUESTION_DIALOG_ID);
			} catch (Exception e) {
				
			}
		}
	}
	
	/* ******************************************************
	 * 
	 * Tapped player
	 * 
	 *******************************************************/
	private void fillTappedTable() {
		
		playerTappedTable.removeAllViews();

		TableRow tr = new TableRow(this);
		
		ImageView image;
		TextView tvPoints, tvItems;
		Button tvSendMessage, tvViewMore;

		InGamePlayerInfoTO p = genericGameResponseTO.getInGamePlayerInfoTO(
				tappedPlayerLogin);
		
		image = new ImageView(this);
		image.setImageDrawable(getResources().getDrawable(p.getImageId()));
		tr = new TableRow(this);
        tr.addView(image);
        tr.setGravity(Gravity.CENTER);
        playerTappedTable.addView(tr);

        tvPoints = new TextView(this);
        tvPoints.setText("Points :\t" + String.valueOf(p.getPoints()));
        tvPoints.setWidth(260);
        tr = new TableRow(this);
        tr.addView(tvPoints);
        tr.setGravity(Gravity.CENTER);
        playerTappedTable.addView(tr);
        
        tvItems = new TextView(this);
        tvItems.setText("Items :\t" + String.valueOf(p.getNumberOfItems()));
        tvItems.setWidth(260);
        tr = new TableRow(this);
        tr.addView(tvItems);
        tr.setGravity(Gravity.CENTER);
        playerTappedTable.addView(tr);
        
        tvSendMessage = new Button(this);
        tvSendMessage.setText("Send Message");
        tvSendMessage.setOnClickListener(new android.view.View.OnClickListener() {

			public void onClick(View v) {
				Intent i = new Intent(MapViewActivity.this, SendMessageActivity.class);
	        	i.putExtra("receiverLogin", tappedPlayerLogin);
	        	startActivityForResult(i, SEND_MESSAGE_REQUEST_CODE);
	        	try {
	        		dismissDialog(PLAYER_TAPPED_DIALOG_ID);
	        	} catch (Exception e) {
	        		
	        	}
			}
        	
        });
        tr = new TableRow(this);

        tvViewMore = new Button(this);
        tvViewMore.setText("More Info");
        tvViewMore.setWidth(LayoutParams.FILL_PARENT);
        tvViewMore.setOnClickListener(
        		new ViewPublicPlayerProfileListener(tappedPlayerLogin));
        tr = new TableRow(this);
        tr.addView(tvViewMore);
        tr.setGravity(Gravity.CENTER);
        playerTappedTable.addView(tr);
        tr = new TableRow(this);
        tvSendMessage.setWidth(LayoutParams.FILL_PARENT);
        tr.addView(tvSendMessage);
        tr.setGravity(Gravity.CENTER);
        playerTappedTable.addView(tr);
	}


	private List<InGamePlayerInfoTO> orderList(List<InGamePlayerInfoTO> plTOList) {
		for (int i=0;i<plTOList.size();i++) {
			for (int j=i+1;j<plTOList.size();j++) {
				if (plTOList.get(i).getPoints() < plTOList.get(j).getPoints()) {
					InGamePlayerInfoTO temp = plTOList.get(i);
					plTOList.set(i, plTOList.get(j));
					plTOList.set(j, temp);
				}
			}
		}
		return plTOList;
	}

	/* ******************************************************
	 * 
	 * Player profile
	 * 
	 *******************************************************/
	
	private class ViewPublicPlayerProfileListener 
	implements android.view.View.OnClickListener {
		
		private String login;
		ViewPublicPlayerProfileListener(String login) {
			this.login = login;
		}
		
		public void onClick(View v) {
			Intent i = new Intent(MapViewActivity.this, ViewPublicPlayerProfileActivity.class);
			i.putExtra("login", login);
			startActivity(i);
		}
	}
	
	/* ******************************************************
	 * 
	 * Answer Question
	 * 
	 *******************************************************/
	private void doAnswerQuestion() {
		String i = new String("bonus");
		if (answerQuestionResponseTO.getNumberOfBonusOpened() > 1)
			i = i.concat("es");
		Toast.makeText(MapViewActivity.this, "Right answer!!\nNow you can see " +
				String.valueOf(answerQuestionResponseTO.getNumberOfBonusOpened()) + 
				i + "!!\nCatching a bonus will give you many points.", Toast.LENGTH_LONG).show();
		
		genericGameResponseTO = 
			answerQuestionResponseTO.getGenericGameResponseTO();

		update();
	}

	private void launchAnswerQuestionThread(long questionId) {
		answerQuestionTask.setQuestionId(questionId);
		answerQuestionTask.setLatitude(player.getLocation().getLatitudeE6());
		answerQuestionTask.setLongitude(player.getLocation().getLongitudeE6());
		Thread answerQuestionThread = new Thread(null, answerQuestionTask, "Login");
		answerQuestionThread.start();
		showDialog(CommonDialogs.CONNECTING_TO_SERVER_DIALOG_ID);
	}

	private void doGetItem(Item item) {
		if (getItemResponseTO.isActuallyTaken()) {
			player.setNumberOfItems(player.getNumberOfItems() + 1);
			player.setPoints(player.getPoints() + 
					item.getPoints());
			String itemName = new String();
			String questionExtra = new String();
			switch(item.getType()) {
			case Item.COIN_TYPE:
				itemName = "coin";
				break;
			case Item.QUESTION_TYPE:
				questionId = item.getItemId();
				itemName = "question";
				questionExtra =  ". Now... will you answer this " +
					"question?";
				break;
			case Item.BONUS_TYPE:
				itemName = "bonus";
				break;
			}

        	if (!getItemResponseTO.getGenericGameResponseTO().isHasFinished()) {
        		LinearLayout v = new LinearLayout(this);
        		TextView tv = new TextView(this);
        		tv.setText("Great!\nYou caughted a " + itemName +
						"\t(" + String.valueOf(item.getPoints()) + " points!!)" + 
						questionExtra);
        		tv.setTextColor(Color.WHITE);
        		tv.setGravity(Gravity.CENTER);
        		v.setOrientation(LinearLayout.VERTICAL);
        		v.addView(tv);
        		v.setBackgroundResource(R.drawable.table_background);
        		if (options.isShowRankingOnGet()) {
	        		fillRankingTable();
	
	        		rankingScrollView = new ScrollView(this);
	        		rankingScrollView.setVerticalScrollBarEnabled(true);
	        		rankingScrollView.addView(rankingTable);
	        		v.addView(rankingScrollView);
        		}
	        	Toast toast = new Toast(this);
				toast.setDuration(Toast.LENGTH_LONG);
				toast.setView(v);
				toast.show();
				if (item.getType() == Item.QUESTION_TYPE)
					showDialog(SHOW_QUESTION_DIALOG_ID);
        	}
			
			getItemResponseTO.setItemId(item.getItemId());
			
			genericGameResponseTO = 
				getItemResponseTO.getGenericGameResponseTO();
		}
		update();
	}
	
	private void launchGetItemThread(Item item, int latitude, int longitude) {
		getItemTask.setItem(item);
		getItemTask.setLatitude(latitude);
		getItemTask.setLatitude(longitude);
		Thread getItemThread = new Thread(null, getItemTask, "GetItemGame");
		getItemThread.start();
	}

	private void doUpdateLocation() {
		update();
	}

	private void launchUpdateLocationThread(int latitude, int longitude) {
		updateLocationTask.setLatitude(latitude);
		updateLocationTask.setLongitude(longitude);
		Thread updateLocationThread = new Thread(null, updateLocationTask, "UpdateLocationGame");
		updateLocationThread.start();
	}
	
	/* ******************************************************
	 * 
	 * Dialogs
	 * 
	 *******************************************************/
	@Override
	protected void onPrepareDialog(int id, Dialog dialog) {
		switch(id) {
        case RANKING_DIALOG_ID:
        	fillRankingTable();
        	rankingScrollView = new ScrollView(this);
    		rankingScrollView.setVerticalScrollBarEnabled(true);
    		rankingScrollView.addView(rankingTable);
        	dialog.setContentView(rankingScrollView);
        	return;
        case PLAYER_TAPPED_DIALOG_ID:
			playerTappedTable = new TableLayout(this);
        	fillTappedTable();
        	dialog.setContentView(playerTappedTable);
        	return;
        case SHOW_QUESTION_DIALOG_ID:
			questionTable = new TableLayout(this);
        	fillQuestion();
        	dialog.setContentView(questionTable);
        	return;
		}
	}

	@Override
    protected Dialog onCreateDialog(int id) {
		Dialog d = CommonDialogs.createDialog(id, this);
		if (d != null)
			return d;
    	switch(id) {
    	case SHOW_QUESTION_DIALOG_ID:
    		d = new Dialog(this);
        	d.setTitle("Question");
        	d.setCanceledOnTouchOutside(true);
        	return d;
        case RANKING_DIALOG_ID:
        	d = new Dialog(this);
        	d.setTitle("Ranking (Goal : " + String.valueOf(game.getPointsToWin()) + " points)");
        	d.setCanceledOnTouchOutside(true);
        	return d;
        case PLAYER_TAPPED_DIALOG_ID:
        	d = new Dialog(this);
        	d.setTitle(tappedPlayerLogin);
        	d.setCanceledOnTouchOutside(true);
        	return d;
        case ABANDON_DIALOG_ID:
        	return new AlertDialog.Builder(this)
            .setIcon(R.drawable.alert_dialog_icon)
            .setTitle("Really quit?")
            .setPositiveButton(R.string.ok, new OnClickListener() {

				public void onClick(DialogInterface arg0, int arg1) {
					lm.removeUpdates(MapViewActivity.this);
					CommonActions.launchAbandonGameThread(
							player, game, MapViewActivity.this);
				}
            })
           .setNegativeButton(R.string.cancel, new OnClickListener() {

				public void onClick(DialogInterface arg0, int arg1) {
					try {
			        	arg0.dismiss();
		        	} catch (Exception e) {
		        		CommonDialogs.errorMessage = e.getLocalizedMessage();
		        		showDialog(CommonDialogs.SERVER_ERROR_DIALOG_ID);
		        	}
				}
           	
           })
          .create();
    	}
    	return null;
    }
	
	
	
	public void doAfterAbandon() {
		Intent mIntent = new Intent();
		Bundle extras = new Bundle();
		player.setLocation(null);
		extras.putSerializable("player", player);
		
		if (genericGameResponseTO.isHasFinished()) {
			extras.putLong("gameId", game.getGameId());
			mIntent.putExtras(extras);
			setResult(CustomResultCodes.GAME_FINISHED_RESULT_CODE, mIntent);
		}
		else {
			mIntent.putExtras(extras);
			setResult(CustomResultCodes.ABANDONED_RESULT_CODE, mIntent);
		}
		finish();
	}

	/* ******************************************************
	 * 
	 * Menu
	 * 
	 *******************************************************/
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        super.onCreateOptionsMenu(menu);
        menu.add(0, ABANDON_ID, 0, "Abandon Game").setIcon(R.drawable.abandon);
        menu.add(0, SEND_BROADCAST_ID, 0, "Send broadcast message").
        	setIcon(R.drawable.message);
        menu.add(0, RANKING_ID, 0, "Ranking").setIcon(R.drawable.ranking);
        menu.add(0, OPTIONS_ID, 0, "Options").setIcon(R.drawable.options);
        return true;
    }
	
	@Override
    public boolean onMenuItemSelected(int featureId, MenuItem item) {
        switch(item.getItemId()) {
        case ABANDON_ID:
        	showDialog(ABANDON_DIALOG_ID);
        	break;
        case SEND_BROADCAST_ID:
        	Intent i = new Intent(this, SendMessageActivity.class);
        	i.putExtra("receiverLogin", (String)null);
        	startActivityForResult(i, SEND_MESSAGE_REQUEST_CODE);
        	break;
        case RANKING_ID:
        	showDialog(RANKING_DIALOG_ID);
        	break;
        case OPTIONS_ID:
        	i = new Intent(this, OptionsActivity.class);
        	i.putExtra("options", options);
        	startActivityForResult(i, OPTIONS_REQUEST_CODE);
        	break;
        }
        return super.onMenuItemSelected(featureId, item);
    }
	
	/* ******************************************************
	 * 
	 * Activity results
	 * 
	 *******************************************************/
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		super.onActivityResult(requestCode, resultCode, data);
		switch(requestCode) {
		case SEND_MESSAGE_REQUEST_CODE:
			switch(resultCode) {
			case RESULT_OK:
				Toast.makeText(this, "Message sent", Toast.LENGTH_LONG).show();
				break;
			}
			break;
		case OPTIONS_REQUEST_CODE:
			switch(resultCode) {
			case RESULT_OK:
				options = (Options)data.getExtras().getSerializable("options");
				lm.removeUpdates(this);
				lm.requestLocationUpdates(
						LocationManager.GPS_PROVIDER, 
						options.getUpdatesInterval(), 10, 
						this);

				Toast.makeText(MapViewActivity.this, "Saved", Toast.LENGTH_LONG).show();
			}
		}
	}
	
	/* ******************************************************
	 * 
	 * Item Overlay
	 * 
	 *******************************************************/
	private class ItemsOverlay extends ItemizedOverlay<OverlayItem> {

		private List<OverlayItemItem> items = new ArrayList<OverlayItemItem>();
		private Drawable marker, marker2, marker3;
		
		public ItemsOverlay(Drawable defaultMarker) {
			super(defaultMarker);
			this.marker = defaultMarker;
			
			update();			
		}
		
		@Override
		public boolean onTap(int i) {
			
			Item item = items.get(i).item; 
			String itemType = new String();
			switch(item.getType()) {
			case Item.COIN_TYPE:
				itemType = "Coin";
				break;
			case Item.QUESTION_TYPE:
				itemType = "Question";
				break;
			case Item.BONUS_TYPE:
				itemType = "Bonus";
				break;
			}
			Toast.makeText(MapViewActivity.this, "Item :\t" + itemType +
					"\n" + "Points :\t" + String.valueOf(item.getPoints()), Toast.LENGTH_LONG).show();
			return true;
		}

		public void update() {
			this.items.clear();
			for (Item item:genericGameResponseTO.getVisibleItems()) {
				items.add(
						new OverlayItemItem(item.getLocation(), 
								String.valueOf(item.getItemId()), "ha", item));
			}

			populate();
			marker2 = getResources().getDrawable(R.drawable.question);
			marker3 = getResources().getDrawable(R.drawable.bonus);
			for (int i=0;i<items.size();i++) {
				if (items.get(i).item.getType() == Item.QUESTION_TYPE)
					items.get(i).setMarker(marker2);
				else if (items.get(i).item.getType() == Item.BONUS_TYPE)
					items.get(i).setMarker(marker3);
			}
		}

		@Override
		public void draw(Canvas canvas, MapView mapView, boolean shadow) {
			super.draw(canvas, mapView, shadow);
			boundCenterBottom(marker);
			boundCenterBottom(marker2);
			boundCenterBottom(marker3);
		}


		@Override
		protected OverlayItem createItem(int arg0) {
			return items.get(arg0);
		}

		@Override
		public int size() {
			return items.size();
		}
	}
	
	private class OverlayItemItem extends OverlayItem {
		private Item item;
		public OverlayItemItem(GeoPoint geoPoint, String title, String snippet,
				Item item) {
			super(geoPoint, title, snippet);
			this.item = item;
		}
		public Item getItem() {
			return item;
		}
		public void setItem(Item item) {
			this.item = item;
		}
	}
	
	/* ******************************************************
	 * 
	 * Players Overlay
	 * 
	 *******************************************************/
	private class PlayersOverlay extends ItemizedOverlay<OverlayItem> {

		private List<OverlayItemPlayer> players = 
			new ArrayList<OverlayItemPlayer>();
		private Drawable marker, marker2, marker3;
		
		public PlayersOverlay(Drawable defaultMarker) {
			super(defaultMarker);
			this.marker = defaultMarker;
			
			update();
		}
		
		@Override
		public boolean onTap(int i) {
			try {
				tappedPlayerLogin = players.get(i).getTitle();
				showDialog(PLAYER_TAPPED_DIALOG_ID);
			} catch (Exception e) {
				CommonDialogs.errorMessage = e.getLocalizedMessage();
				showDialog(CommonDialogs.CLIENT_ERROR_DIALOG_ID);
			}
			return true;
		}

		public void update() {
			this.players.clear();
			for (InGamePlayerInfoTO iGPITO:genericGameResponseTO.getInGamePlayerInfoTOs()) {
				players.add(
						new OverlayItemPlayer(iGPITO.getLocation(), 
								String.valueOf(iGPITO.getLogin()), "ha", iGPITO));
			}
			populate();
			marker2 = getResources().getDrawable(
					ImageResolver.getOtherInGameImageId(R.drawable.face2));
			marker3 = getResources().getDrawable(
					ImageResolver.getOtherInGameImageId(R.drawable.face3));
			for (int i=0;i<players.size();i++) {
				if (players.get(i).inGamePlayerInfoTO.getImageId() == R.drawable.face2)
					players.get(i).setMarker(marker2);
				else if (players.get(i).inGamePlayerInfoTO.getImageId() == R.drawable.face3)
					players.get(i).setMarker(marker3);
			}
		}
		
		@Override
		public void draw(Canvas canvas, MapView mapView, boolean shadow) {
			super.draw(canvas, mapView, shadow);
			boundCenterBottom(marker);
			boundCenterBottom(marker2);
			boundCenterBottom(marker3);
		}


		@Override
		protected OverlayItem createItem(int arg0) {
			return players.get(arg0);
		}

		@Override
		public int size() {
			return players.size();
		}
	}
	
	private class OverlayItemPlayer extends OverlayItem {
		private InGamePlayerInfoTO inGamePlayerInfoTO;
		public OverlayItemPlayer(GeoPoint geoPoint, String title, String snippet,
				InGamePlayerInfoTO inGamePlayerInfoTO) {
			super(geoPoint, title, snippet);
			this.inGamePlayerInfoTO = inGamePlayerInfoTO;
		}
		
		public InGamePlayerInfoTO getInGamePlayerInfoTO() {
			return inGamePlayerInfoTO;
		}
		
		public void setInGamePlayerInfoTO(InGamePlayerInfoTO inGamePlayerInfoTO) {
			this.inGamePlayerInfoTO = inGamePlayerInfoTO;
		}
		
	}

	/* ******************************************************
	 * 
	 * My player Overlay
	 * 
	 *******************************************************/
	private class MyPlayerOverlay extends ItemizedOverlay<OverlayItem> {

		private List<OverlayItem> playerList = new ArrayList<OverlayItem>();
		private Drawable marker;

		public MyPlayerOverlay(Drawable defaultMarker) {
			super(defaultMarker);
			
			this.marker = defaultMarker;

			playerList.add(
					new OverlayItem(player.getLocation(), 
								String.valueOf(player.getLogin()), "Me"));

			populate();
		}

		@Override
		public boolean onTap(int i) {
			Toast toast = 
				Toast.makeText(
						MapViewActivity.this, "Hei, this is me!", Toast.LENGTH_LONG);
			toast.show();
			return true;
		}

		@Override
		public void draw(Canvas canvas, MapView mapView, boolean shadow) {
			super.draw(canvas, mapView, shadow);
			boundCenterBottom(marker);
		}

		public void update() {
			playerList.remove(0);
			playerList.add(
					new OverlayItem(player.getLocation(), 
								String.valueOf(player.getLogin()), "Me"));
			populate();
		}
		
		@Override
		protected OverlayItem createItem(int arg0) {
			return playerList.get(arg0);
		}

		@Override
		public int size() {
			return playerList.size();
		}
	}
	
	/* ******************************************************
	 * 
	 * Location listener
	 * 
	 *******************************************************/
	public void onLocationChanged(Location location) {
		player.setLocation(LocationToGeoPointConversor.getGeoPoint(location));
		for (int i=0;i<itemsLayer.size();i++) {
			Item item = itemsLayer.items.get(i).item;
			if (location.distanceTo(LocationToGeoPointConversor.getLocation(item.getLocation())) < 10) {
					launchGetItemThread(item, player.getLocation().getLatitudeE6(),
						player.getLocation().getLongitudeE6());
				return;
			}
		}
		launchUpdateLocationThread(player.getLocation().getLatitudeE6(),
				player.getLocation().getLongitudeE6());
		return;
	}

	public void onProviderDisabled(String provider) {
	}

	public void onProviderEnabled(String provider) {
	}

	public void onStatusChanged(String provider, int status,
			Bundle extras) {
	}
	
	private class StartGameHandler extends Handler {

		public StartGameHandler(Looper looper) {
			super(looper);
		}
		
		@Override
		public void handleMessage(android.os.Message msg) {
			try {
				dismissDialog(CommonDialogs.CONNECTING_TO_SERVER_DIALOG_ID);
			} catch (Exception e) {
				
			}
			ServerException sE = 
				(ServerException)msg.getData().getSerializable("ServerException");
			if (sE	!= null) {
				CommonDialogs.errorMessage = sE.getMessage();
				if (sE.getCode() == ServerException.INSTANCE_NOT_FOUND_CODE)
					showDialog(CommonDialogs.CONNECTION_LOST_DIALOG_ID);
				else
					showDialog(CommonDialogs.SERVER_ERROR_DIALOG_ID);
	        	return;
	        }
        	Exception e = 
	        	(Exception)msg.getData().getSerializable("Exception");
	        	if (e != null) {
	        		CommonDialogs.errorMessage = e.getMessage();
		        	showDialog(CommonDialogs.CLIENT_ERROR_DIALOG_ID);
		        	return;
	        	}
			StartOrContinueGameResponseTO sOCGRTO2 = 
				(StartOrContinueGameResponseTO)msg.getData().getSerializable("sOCGRTO");
			if (sOCGRTO2 != null) {
				sOCGRTO = sOCGRTO2;
				doStartGame();
			}
		}
		
	}
	
	private class StartGameTask implements Runnable {

		String login;
		HttpGameServiceImpl gameService;
		
		public String getLogin() {
			return login;
		}

		public void setLogin(String login) {
			this.login = login;
		}

		StartGameTask() {
			gameService = new HttpGameServiceImpl();
		}
		
		public void run() {
			
			StartGameHandler handler = new StartGameHandler(Looper.getMainLooper());
			Bundle data = new Bundle();
			android.os.Message msg = new android.os.Message();
			try {
				StartOrContinueGameResponseTO sOCGRTO = 
					gameService.startOrContinueGame(login);
				data.putSerializable("sOCGRTO", sOCGRTO);
				msg.setData(data);
				handler.sendMessage(msg);
				
			} catch (ServerException e) {
	        	data.putSerializable("ServerException", e);
	        	msg.setData(data);
				handler.sendMessage(msg);
	        } catch (Exception e) {
	        	data.putSerializable("Exception", e);
	        	msg.setData(data);
				handler.sendMessage(msg);
	        }
		}
	}
	
	private class ViewPublicPlayerProfileHandler extends Handler {

		public ViewPublicPlayerProfileHandler(Looper looper) {
			super(looper);
		}
		
		@Override
		public void handleMessage(android.os.Message msg) {
			try {
				dismissDialog(CommonDialogs.CONNECTING_TO_SERVER_DIALOG_ID);
			} catch (Exception e) {
				
			}
			ServerException sE = 
				(ServerException)msg.getData().getSerializable("ServerException");
			if (sE	!= null) {
				CommonDialogs.errorMessage = sE.getMessage();
	        	showDialog(CommonDialogs.SERVER_ERROR_DIALOG_ID);
	        	return;
	        }
        	Exception e = 
	        	(Exception)msg.getData().getSerializable("Exception");
	        	if (e != null) {
	        		CommonDialogs.errorMessage = e.getLocalizedMessage();
		        	showDialog(CommonDialogs.CLIENT_ERROR_DIALOG_ID);
		        	return;
	        	}
			PublicPlayerProfileTO pPPTO2 = 
				(PublicPlayerProfileTO)msg.getData().getSerializable("pPPTO");
			if (pPPTO2 != null) {
				publicPlayerProfileTO = pPPTO2;
				doContinueFinishing();
			}
		}
	}
	
	private class ViewPublicPlayerProfileTask implements Runnable {

		String login;
		HttpPlayerServiceImpl playerService;
		
		public String getLogin() {
			return login;
		}

		public void setLogin(String login) {
			this.login = login;
		}

		ViewPublicPlayerProfileTask() {
			playerService = new HttpPlayerServiceImpl();
		}
		
		public void run() {
			
			ViewPublicPlayerProfileHandler handler = 
				new ViewPublicPlayerProfileHandler(Looper.getMainLooper());
			Bundle data = new Bundle();
			android.os.Message msg = new android.os.Message();
			try {
				PublicPlayerProfileTO pPPTO = 
					playerService.getPublicPlayerProfile(login);
				data.putSerializable("pPPTO", pPPTO);
				msg.setData(data);
				handler.sendMessage(msg);
				
			} catch (ServerException e) {
	        	data.putSerializable("ServerException", e);
	        	msg.setData(data);
				handler.sendMessage(msg);
	        } catch (Exception e) {
	        	data.putSerializable("Exception", e);
	        	msg.setData(data);
				handler.sendMessage(msg);
	        }
		}
	}
	
	private class AnswerQuestionHandler extends Handler {

		public AnswerQuestionHandler(Looper looper) {
			super(looper);
		}
		
		@Override
		public void handleMessage(android.os.Message msg) {
			try {
				dismissDialog(CommonDialogs.CONNECTING_TO_SERVER_DIALOG_ID);
			} catch (Exception e) {
				
			}
			ServerException sE = 
				(ServerException)msg.getData().getSerializable("ServerException");
			if (sE	!= null) {
				CommonDialogs.errorMessage = sE.getMessage();
				if (sE.getCode() == ServerException.INSTANCE_NOT_FOUND_CODE)
					showDialog(CommonDialogs.CONNECTION_LOST_DIALOG_ID);
				else
					showDialog(CommonDialogs.SERVER_ERROR_DIALOG_ID);
	        	return;
	        }
        	Exception e = 
	        	(Exception)msg.getData().getSerializable("Exception");
	        	if (e != null) {
	        		CommonDialogs.errorMessage = e.getLocalizedMessage();
		        	showDialog(CommonDialogs.CLIENT_ERROR_DIALOG_ID);
		        	return;
	        	}
			AnswerQuestionResponseTO aQRTO2 = 
				(AnswerQuestionResponseTO)msg.getData().getSerializable("aQRTO");
			if (aQRTO2 != null) {
				answerQuestionResponseTO = aQRTO2;
				doAnswerQuestion();
			}
		}
	}
	
	private class AnswerQuestionTask implements Runnable {

		long questionId;
		int latitude, longitude;
		HttpGameServiceImpl gameService;
		
		public long getQuestionId() {
			return questionId;
		}

		public void setQuestionId(long questionId) {
			this.questionId = questionId;
		}

		public int getLatitude() {
			return latitude;
		}

		public void setLatitude(int latitude) {
			this.latitude = latitude;
		}

		public int getLongitude() {
			return longitude;
		}

		public void setLongitude(int longitude) {
			this.longitude = longitude;
		}

		AnswerQuestionTask() {
			gameService = new HttpGameServiceImpl();
		}
		
		public void run() {
			
			AnswerQuestionHandler handler = new AnswerQuestionHandler(Looper.getMainLooper());
			Bundle data = new Bundle();
			android.os.Message msg = new android.os.Message();
			try {
				AnswerQuestionResponseTO aQRTO = 
					gameService.answerQuestion(
							questionId, latitude, longitude);
				data.putSerializable("aQRTO", aQRTO);
				msg.setData(data);
				handler.sendMessage(msg);
				
			} catch (ServerException e) {
	        	data.putSerializable("ServerException", e);
	        	msg.setData(data);
				handler.sendMessage(msg);
	        } catch (Exception e) {
	        	data.putSerializable("Exception", e);
	        	msg.setData(data);
				handler.sendMessage(msg);
	        }
		}
	}
	
	
	private class GetItemHandler extends Handler {

		public GetItemHandler(Looper looper) {
			super(looper);
		}
		
		@Override
		public void handleMessage(android.os.Message msg) {
			ServerException sE = 
				(ServerException)msg.getData().getSerializable("ServerException");
			if (sE	!= null) {
				CommonDialogs.errorMessage = sE.getMessage();
				if (sE.getCode() == ServerException.INSTANCE_NOT_FOUND_CODE)
					showDialog(CommonDialogs.CONNECTION_LOST_DIALOG_ID);
				else
					showDialog(CommonDialogs.SERVER_ERROR_DIALOG_ID);
	        	return;
	        }
        	Exception e = 
	        	(Exception)msg.getData().getSerializable("Exception");
	        	if (e != null) {
	        		CommonDialogs.errorMessage = e.getLocalizedMessage();
		        	showDialog(CommonDialogs.CLIENT_ERROR_DIALOG_ID);
		        	return;
	        	}
	        	GetItemResponseTO gIRTO2 = 
	        		(GetItemResponseTO)msg.getData().getSerializable("gIRTO");
	        	Item item2 =
	        		(Item)msg.getData().getSerializable("item");
			if (gIRTO2 != null) {
				getItemResponseTO = gIRTO2;
				doGetItem(item2);
			}
		}
	}
	
	private class GetItemTask implements Runnable {

		Item item;
		int latitude, longitude;
		HttpGameServiceImpl gameService;
		
		public Item getItem() {
			return item;
		}

		public void setItem(Item item) {
			this.item = item;
		}

		public int getLatitude() {
			return latitude;
		}

		public void setLatitude(int latitude) {
			this.latitude = latitude;
		}

		public int getLongitude() {
			return longitude;
		}

		public void setLongitude(int longitude) {
			this.longitude = longitude;
		}

		GetItemTask() {
			gameService = new HttpGameServiceImpl();
		}
		
		public void run() {
			
			GetItemHandler handler = 
				new GetItemHandler(Looper.getMainLooper());
			Bundle data = new Bundle();
			android.os.Message msg = new android.os.Message();
			try {
				GetItemResponseTO gIRTO = 
					gameService.getItem(
							latitude, longitude, item.getItemId());
				data.putSerializable("gIRTO", gIRTO);
				data.putSerializable("item", item);
				msg.setData(data);
				handler.sendMessage(msg);
				
			} catch (ServerException e) {
	        	data.putSerializable("ServerException", e);
	        	msg.setData(data);
				handler.sendMessage(msg);
	        } catch (Exception e) {
	        	data.putSerializable("Exception", e);
	        	msg.setData(data);
				handler.sendMessage(msg);
	        }
		}
	}
	
	private class UpdateLocationHandler extends Handler {

		public UpdateLocationHandler(Looper looper) {
			super(looper);
		}
		
		@Override
		public void handleMessage(android.os.Message msg) {
			ServerException sE = 
				(ServerException)msg.getData().getSerializable("ServerException");
			if (sE	!= null) {
				CommonDialogs.errorMessage = sE.getMessage();
	        	if (sE.getCode() == ServerException.INSTANCE_NOT_FOUND_CODE)
					showDialog(CommonDialogs.CONNECTION_LOST_DIALOG_ID);
				else
					showDialog(CommonDialogs.SERVER_ERROR_DIALOG_ID);
	        	return;
	        }
        	Exception e = 
	        	(Exception)msg.getData().getSerializable("Exception");
	        	if (e != null) {
	        		CommonDialogs.errorMessage = e.getLocalizedMessage();
		        	showDialog(CommonDialogs.CLIENT_ERROR_DIALOG_ID);
		        	return;
	        	}
	        GenericGameResponseTO gGRTO2 = 
				(GenericGameResponseTO)msg.getData().getSerializable("gGRTO");
			if (gGRTO2 != null) {
				genericGameResponseTO = gGRTO2;
				doUpdateLocation();
			}
		}
	}
	
	private class UpdateLocationTask implements Runnable {

		int latitude, longitude;
		HttpGameServiceImpl gameService;
		
		public int getLatitude() {
			return latitude;
		}

		public void setLatitude(int latitude) {
			this.latitude = latitude;
		}

		public int getLongitude() {
			return longitude;
		}

		public void setLongitude(int longitude) {
			this.longitude = longitude;
		}

		UpdateLocationTask() {
			gameService = new HttpGameServiceImpl();
		}

		public void run() {

			UpdateLocationHandler handler = 
				new UpdateLocationHandler(Looper.getMainLooper());
			Bundle data = new Bundle();
			android.os.Message msg = new android.os.Message();
			try {
				GenericGameResponseTO gGRTO = 
					gameService.updateLocation(
							latitude, longitude);
				data.putSerializable("gGRTO", gGRTO);
				msg.setData(data);
				handler.sendMessage(msg);
				
			} catch (ServerException e) {
	        	data.putSerializable("ServerException", e);
	        	msg.setData(data);
				handler.sendMessage(msg);
	        } catch (Exception e) {
	        	data.putSerializable("Exception", e);
	        	msg.setData(data);
				handler.sendMessage(msg);
	        }
		}
	}
}
